package com.atguigu.tingshu.common.login;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import jodd.util.StringUtil;
import lombok.SneakyThrows;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.jwt.crypto.sign.RsaVerifier;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.lang.reflect.Method;

import static com.atguigu.tingshu.common.result.ResultCodeEnum.*;


@Component
@Aspect
public class LongAspect {
    /**
     * 环绕切面类，登录验证
     * @param point
     * @return
     */
    @SneakyThrows
    @Around(value = "@annotation(com.atguigu.tingshu.common.login.GuiLogin)")
    public Object loginCheck(ProceedingJoinPoint point) {
        //通过注解获取当前请求是否需要登录
        //通过poin获取方法签名
        MethodSignature signature = (MethodSignature)point.getSignature();
        //根据签名获取方法对象
        Method method = signature.getMethod();
        //根据方法对象获取注解
        GuiLogin annotation = method.getAnnotation(GuiLogin.class);
        //根据注解获取注解内容，根据注解内容进行判断是否需要登录
        if (annotation.isLogin()){
            //如果为true，需要登录，检验token
            //从RequestContextHolder获取请求标签
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
            //从请求标签获取请求头。从请求头获取token
            String token = requestAttributes.getRequest().getHeader("token");
            if (token==null){
                throw new GuiguException(LOGIN_AUTH);
            }
            //解密token
            try {
                Jwt jwt = JwtHelper.decodeAndVerify(token, new RsaVerifier(SystemConstant.PUBLIC_KEY));
                //获取载荷
                String claims = jwt.getClaims();
                //反序列化
                JSONObject jsonObject = JSONObject.parseObject(claims);
                //获取旧token的生成时间
                Long time = jsonObject.getLong("Time");
                //判断token是否大10分钟
                long duration = System.currentTimeMillis() - time;
//                if (duration >= 600000){
//                    //如果大于大10分钟，抛出签名过期异常给前端
//                    throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
//                } else if (duration >= 300000) {
//                    //抛出token已过期给前端，
//                    throw new GuiguException(SIGN_OVERDUE);
//                }
                //获取用户id
                Long userId = jsonObject.getLong("userId");
                //用户id存入本地线程
                AuthContextHolder.setUserId(userId);

                String vipExpireTimeString = jsonObject.getString("vipExpireTime");
                if(!StringUtil.isEmpty(vipExpireTimeString)){
                    AuthContextHolder.setvipExpireTime(Long.valueOf(vipExpireTimeString));
                }
            }catch (Exception  e){
                throw  new GuiguException(ResultCodeEnum.LOGIN_AUTH);
            }
            //获取方法参数
            Object[] args = point.getArgs();
            //执行方法
            Object proceed = point.proceed(args);
            //清理本地线程
            AuthContextHolder.removeUserId();
            return proceed;
        }
        return point.proceed();
    }
}
